#include "server.hpp"

// 为新连接设置的回调函数
void HandleRead(Channel *channel);
void HandleWrite(Channel *channel);
void HandleClose(Channel *channel);
void HandleError(Channel *channel);
void HandleEvent(Channel *channel);

// lst_sock 获取新连接的套接字设置的回调函数
void Acceptor(EventLoop *loop, Channel *lst_channel)
{
    int fd = lst_channel->Fd(); // 这里的话就是获取监听套接字

    // 1. 新获取上来的文件描述符 int newfd;
    int newfd = accept(fd, nullptr, nullptr);
    if (newfd < 0)
        return;
    // 2. 为新获取上来的文件描述符设置对应的Channel
    Channel *channel = new Channel(loop, newfd);
    // 3. 设置对应的事件管理
    channel->SetReadCallback(std::bind(HandleRead, channel));
    channel->SetWriteCallback(std::bind(HandleWrite, channel));
    channel->SetCloseCallback(std::bind(HandleClose, channel));
    channel->SetErrorCallback(std::bind(HandleError, channel));
    channel->SetEventCallback(std::bind(HandleEvent, channel));
    // 并添加监控
    channel->EnableRead();
}

// 注意梳理一下代码的执行流 ---> 能更好的理解代码
int main(void)
{
    EventLoop loop;
    Socket lst_sock;
    lst_sock.CreateServer(8500);
    // 为监听套接字，创建一个Channel进行事件的管理，以及事件的处理
    Channel channel(&loop, lst_sock.Fd()); // Poller监控所有的文件描述符
    // 回调中，获取新连接，为新连接创建channel并添加监控。 ----> 添加监控就得用 poller
    channel.SetReadCallback(std::bind(Acceptor, &loop, &channel));
    channel.EnableRead(); // 启动可读事件监控(设置进loop里面的class Poller里面被监控)
    // while (true)
    // {
    //     // 获取活跃连接
    //     std::vector<Channel *> actives;
    //     poller.Poll(&actives);
    //     for (auto &a : actives)
    //         a->HandleEvent();
    // }
    loop.Start();

    return 0;
}

void HandleRead(Channel *channel)
{
    int fd = channel->Fd();
    char buffer[1024] = {0};
    int ret = recv(fd, buffer, sizeof(buffer) - 1, 0);
    if (ret <= 0)
        return HandleClose(channel); // 关闭释放
    std::cout << buffer << std::endl;
    channel->EnableWrite(); // 启动可写事件：读取client发送的信息上来了，接下来就是要发送信息回去了(就启动可写事件嘛)
}

void HandleWrite(Channel *channel)
{
    int fd = channel->Fd();
    std::string data = "天气还不错!!!";
    int ret = send(fd, data.c_str(), data.size(), 0);
    if (ret < 0)
        return HandleClose(channel); // 关闭释放
    // 关闭写监控(不关闭的话，执行channel->HandleEvent()的时候，可写事件一直是可以的，就会一直死循环的触发写事件)
    // 至于可读事件嘛。上面可以看出来，监听套接字为新连接设置了监听就是设置了可读事件(client没有发送的时候，recv是阻塞的。这里的send不同，会一直发送)
    channel->DisableWrite();
}

void HandleClose(Channel *channel)
{
    std::cout << "close: " << channel->Fd() << std::endl;
    // 移除监控
    // class Channel里面有一个Class Poller,Class Poller里面有一个unordered_map<int, Channel*> _channels; 和 int _epfd)
    // 所以，移除的意思是把channel管理的channel->Fd()从epoll里面EPOLL_CTL_DEL +  把channel管理的channel->Fd()从_channels里面_channels.erase(channel->Fd());
    channel->Remove();
    delete channel;
}

void HandleError(Channel *channel)
{
    return HandleClose(channel); // 关闭释放
}

void HandleEvent(Channel *channel)
{
    std::cout << "有了一个事件!!!" << std::endl;
}
